home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / rayshade / graphtal.lzh / Graphtal.Amiga / Plane.C < prev    next >
C/C++ Source or Header  |  1992-11-19  |  5KB  |  217 lines

  1. /*
  2.  * Plane.C - methods for plane manipulations.
  3.  *
  4.  * Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
  5.  *                     University of Berne, Switzerland
  6.  * Copyright (C) 1989, 1991, Craig E. Kolb
  7.  * All rights reserved.
  8.  *
  9.  * This software may be freely copied, modified, and redistributed
  10.  * provided that this copyright notice is preserved on all copies.
  11.  *
  12.  * You may not distribute this software, in whole or in part, as part of
  13.  * any commercial product without the express consent of the authors.
  14.  *
  15.  * There is no warranty or other guarantee of fitness of this software
  16.  * for any purpose.  It is provided solely "as is".
  17.  *
  18.  */
  19.  
  20. #include "Plane.h"
  21.  
  22. //___________________________________________________________ Plane
  23.  
  24. Plane::Plane(const Vector& position, const Vector& normal)
  25. :  pos(position), n(normal)
  26. {
  27.   if (n.normalize() == 0)
  28.   n.normalize();
  29.   D = pos^n;
  30. }
  31.  
  32. GeoObject* Plane::create(const Vector& position, const Vector& normal)
  33. {
  34.   if (equal(normal.sqr(), 0))
  35.     return NULL;
  36.  
  37.   return new Plane(position, normal);
  38. }
  39.  
  40. /*
  41.  * intersect plane with ray.
  42.  */
  43.  
  44. int Plane::intersect(const Ray& ray, real minDist, real& maxDist)
  45. {
  46.   intersectionTests++;
  47.  
  48.   real t = n^ray.getDir();
  49.   if (fabs(t) < minDist)
  50.     return FALSE;
  51.  
  52.   t = (D - (ray.getOrig()^n))/t;
  53.   
  54.   if (t > minDist && t < maxDist) {
  55.     maxDist = t;
  56.     intersections++;
  57.     return TRUE;
  58.   }
  59.   return FALSE;
  60. }
  61.  
  62. /*
  63.  * Compute plane normal
  64.  */
  65.  
  66. Vector Plane::normal(const Vector&) const
  67. {
  68.   return n;
  69. }
  70.  
  71. /*
  72.  * tesselate splits a plane into a polygon (I know it's impossible).
  73.  * It is done by intersecting the plane with the bounding volume. The 
  74.  * resulting polygon is the visible part of the plane within the bounding
  75.  * volume.
  76.  */
  77.  
  78. PolygonList* Plane::tesselate(const BoundingBox& bbox)
  79. {
  80.   int i;
  81.   BoundingBox tbbox(bbox);
  82.   
  83.   if (trans != NULL) 
  84.     tbbox = bbox.transform(*itrans);
  85.  
  86.   /*
  87.    * compute the points on the bounding volume
  88.    */
  89.   Vector bottom[4];
  90.   bottom[0] = Vector(tbbox.xmin(), tbbox.ymin(), tbbox.zmin());
  91.   bottom[1] = Vector(tbbox.xmax(), tbbox.ymin(), tbbox.zmin());
  92.   bottom[2] = Vector(tbbox.xmax(), tbbox.ymax(), tbbox.zmin());
  93.   bottom[3] = Vector(tbbox.xmin(), tbbox.ymax(), tbbox.zmin());
  94.  
  95.   Vector top[4];
  96.   top[0] = Vector(tbbox.xmin(), tbbox.ymin(), tbbox.zmax());
  97.   top[1] = Vector(tbbox.xmax(), tbbox.ymin(), tbbox.zmax());
  98.   top[2] = Vector(tbbox.xmax(), tbbox.ymax(), tbbox.zmax());
  99.   top[3] = Vector(tbbox.xmin(), tbbox.ymax(), tbbox.zmax());
  100.   
  101.   Polygon* p = new Polygon(4);
  102.   PolygonList* polys = NULL;
  103.   Vector iPoint;
  104.   int pointsOnPlane;
  105.  
  106.   for (i=0; i<4; i++) {
  107.     if (pointsOnPlane=intersectPlaneWithSegment(bottom[i], top[i], iPoint)) {
  108.       if (pointsOnPlane == 2) {
  109.         p->addVertex(bottom[i]); 
  110.         p->addVertex(top[i]);
  111.       }
  112.       else
  113.         p->addVertex(iPoint);
  114.     }
  115.   }
  116.   for (i=0; i<4 && p->numVertices() < 4; i++) {
  117.     if (pointsOnPlane=intersectPlaneWithSegment(top[i], top[(i+1)%4], iPoint)) {
  118.       if (pointsOnPlane == 2) {
  119.         p->addVertex(top[i]); 
  120.         p->addVertex(top[(i+1)%4]);
  121.       }
  122.       else
  123.         p->addVertex(iPoint);
  124.     }
  125.   }
  126.   for (i=0; i<4 && p->numVertices() < 4; i++) {
  127.     if (pointsOnPlane=intersectPlaneWithSegment(bottom[i], bottom[(i+1)%4], iPoint)) {
  128.       if (pointsOnPlane == 2) {
  129.         p->addVertex(bottom[i]); 
  130.         p->addVertex(bottom[(i+1)%4]);
  131.       }
  132.       else
  133.         p->addVertex(iPoint);
  134.     }
  135.   }
  136.  
  137.   if (p->numVertices() < 3) {
  138.     delete p; 
  139.     p = NULL;
  140.   }
  141.   else if (p->numVertices() == 4) {
  142.     Vector p1 = p->vertex(0), p2 = p->vertex(1),
  143.            p3 = p->vertex(2), p4 = p->vertex(3);
  144.  
  145.     /*
  146.      * check if any two edges intersects 
  147.      *  -> if yes, swap the corresponding points
  148.      */
  149.     if (!equal(((p2-p1)*(p4-p3)).sqr(),0)) {
  150.       Polygon* swapedP = new Polygon(p1, p2, p4, p3);
  151.       delete p;
  152.       p = swapedP;
  153.     }
  154.     else if (!equal(((p4-p1)*(p2-p3)).sqr(),0)) {
  155.       Polygon* swapedP = new Polygon(p2, p1, p3, p4);
  156.       delete p;
  157.       p = swapedP;
  158.     }
  159.   }
  160.  
  161.   if (p != NULL) {
  162.     if (trans != NULL)
  163.       p->transform(*trans);
  164.     polys = new PolygonList(1);
  165.     polys->append(p);
  166.   }
  167.   
  168.   return polys;
  169. }
  170.  
  171.  
  172. /*
  173.  * Intersect segment p1,p2 with the plane. The return values are
  174.  * 0 (no intersection), 1 (one intersection) or 2 (segment is on the plane).
  175.  */
  176.  
  177. int Plane::intersectPlaneWithSegment(const Vector& p1, const Vector& p2, Vector& h)
  178. {
  179.   /*
  180.    * calculate distance to plane for points p1, p2
  181.    */
  182.   real d1 = (p1 - pos)^n; 
  183.   real d2 = (p2 - pos)^n;
  184.  
  185.   /* 
  186.    * Test if one (both) endpoint(s) of the segment is one the plane.
  187.    */
  188.   if (equal(d1, 0)) {
  189.     if (equal(d2,0))
  190.       return 2;
  191.     else {
  192.       h = p1;
  193.       return 1;
  194.     }
  195.   } 
  196.   else if (equal(d2, 0)) {
  197.     h = p2;
  198.     return 1;
  199.   }
  200.  
  201.   /*
  202.    * If the point p1 and p2 are on the same side of the plane,
  203.    * no intersection is possible.
  204.    */
  205.   if ((d1 < 0 && d2 < 0) || (d1 > 0 && d2 > 0))
  206.     return 0;
  207.  
  208.   Vector dir = p2-p1; dir.normalize();
  209.   real t = n^dir;
  210.  
  211.   h = p1 + ((D-(p1^n))/t)*dir;
  212.  
  213.   return 1;
  214. }
  215.  
  216.  
  217.